package com.myBlog.controller;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.myBlog.pojo.Article;
import com.myBlog.pojo.dict.Tag;
import com.myBlog.pojo.dict.Type;
import com.myBlog.repository.ArticleMapper;
import com.myBlog.repository.DictTagMapper;
import com.myBlog.repository.DictTypeMapper;
import com.myBlog.services.Article.ArticleService;
import com.myBlog.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.concurrent.TimeUnit;

// 字典管理--数据项配置
@Slf4j
@RestController
public class DictController {

    @Autowired
    private DictTypeMapper typeMapper;

    @Autowired
    private DictTagMapper tagMapper;

    @Autowired
    private ArticleService articleDbService;

    @Autowired
    private RedisTemplate redisTemplate;

    public static String redisDictKey = "dict_map";

    @PostMapping("/user/getDict")
    public JSONObject getDictObject(){
        Object cacheMap = redisTemplate.opsForValue().get(redisDictKey);
        if(cacheMap==null){
            this.syncDbDataToRedis();
            cacheMap = redisTemplate.opsForValue().get(redisDictKey);
        }

        return JsonUtil.ok_with_Data(cacheMap);
    }

    // 从数据库同步到redis
    private void syncDbDataToRedis(){
        List<Type> types = typeMapper.selectList(null);
        List<Tag> tags = tagMapper.selectList(null);

        JSONObject object = new JSONObject();
        object.put("types", types);
        object.put("tags", tags);

        // 缓存生存时间半小时
        redisTemplate.opsForValue().set(redisDictKey, object, 30, TimeUnit.MINUTES);
    }

    @PostMapping("/admin/listType")
    public JSONObject listType(){
        return JsonUtil.ok_with_Data(typeMapper.selectList(null));
    }


    @PostMapping("/admin/addType")
    public JSONObject addType(@RequestBody JSONObject req){
        if(!StringUtils.hasLength(req.getString("typeKey"))){
            return JsonUtil.error_info("typeKey 类型标识字符串不得为空");
        }
        if(!StringUtils.hasLength(req.getString("typeText"))){
            return JsonUtil.error_info("typeText 类型文字不得为空");
        }

        Type type = new Type();
        type.setTypeKey(req.getString("typeKey"));
        type.setTypeText(req.getString("typeText"));
        this.insertTypeWithTransaction(type);

        return JsonUtil.ok_info_withDefault();
    }

    @PostMapping("/admin/editType")
    public JSONObject editType(@RequestBody Type req){
        this.editTypeWithTransaction(req);
        return JsonUtil.ok_info_withDefault();
    }

    @PostMapping("/admin/deleteType")
    public JSONObject deleteType(@RequestBody Type req){
        if(!StringUtils.hasLength(req.getTypeKey())){
            return JsonUtil.error_info("类型标识 typeKey 不存在");
        }
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Article::getType, req.getTypeKey());
        long count = this.articleDbService.count(queryWrapper);
        if(count>0){
            return JsonUtil.error_info("标签标识 typeKey="+req.getTypeKey()+" 被文章使用，请先删除文章标签");
        }

        this.delTypeWithTransaction(req);
        return JsonUtil.ok_info_withDefault();
    }

    @Transactional
    private void insertTypeWithTransaction(Type type){
        typeMapper.insert(type);
        this.syncDbDataToRedis();
    }

    @Transactional
    private void editTypeWithTransaction(Type type){
        typeMapper.updateById(type);
        this.syncDbDataToRedis();
    }

    @Transactional
    private void delTypeWithTransaction(Type type){
        typeMapper.deleteById(type);
        this.syncDbDataToRedis();
    }

    @PostMapping("/admin/listTag")
    public JSONObject listTag(){
        return JsonUtil.ok_with_Data(tagMapper.selectList(null));
    }

    @PostMapping("/admin/addTag")
    public JSONObject addTag(@RequestBody Tag tag){
        if(!StringUtils.hasLength(tag.getTagName())){
            return JsonUtil.error_info("标签名称tagName不得为空");
        }

        this.insertTagDB(tag);
        return JsonUtil.ok_info_withDefault();
    }

    @PostMapping("/admin/editTag")
    public JSONObject editTag(@RequestBody Tag tag){
        if(tag.getTagId()==null){
            return JsonUtil.error_info("标签标识tagId不得为空");
        }
        if(!StringUtils.hasLength(tag.getTagName())){
            return JsonUtil.error_info("标签名称tagName不得为空");
        }

        this.editTagDB(tag);
        return JsonUtil.ok_info_withDefault();
    }

    @PostMapping("/admin/deleteTag")
    public JSONObject deleteTag(@RequestBody Tag tag){
        if(tag.getTagId()==null){
            return JsonUtil.error_info("标签标识tagId不得为空");
        }
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Article::getTags, tag.getTagId());
        long count = this.articleDbService.count(queryWrapper);
        if(count>0){
            return JsonUtil.error_info("标签标识 tagId="+tag.getTagId()+" 被文章使用，请先删除文章标签");
        }

        this.deleteTagDB(tag);
        return JsonUtil.ok_info_withDefault();
    }

    @Transactional
    private void insertTagDB(Tag tag){
        tag.setTagId(null);
        tagMapper.insert(tag);
        this.syncDbDataToRedis();
    }

    @Transactional
    private void editTagDB(Tag tag){
        tagMapper.updateById(tag);
        this.syncDbDataToRedis();
    }

    @Transactional
    private void deleteTagDB(Tag tag){
        tagMapper.deleteById(tag);
        this.syncDbDataToRedis();
    }
}
